              <div align="right">
${TARGET="offline"}                <a href="${LDAP_SDK_HOME_URL}" style="font-size: 85%">LDAP SDK Home Page</a>
                <br>
                <a href="${BASE}index.${EXTENSION}" style="font-size: 85%">Product Information</a>
                <br>
                <a href="index.${EXTENSION}" style="font-size: 85%">Getting Started with the LDAP SDK</a>
              </div>

              <h2>Creating and Using LDAP Connection Pools</h2>

              <p>
                An LDAP connection pool, provides a mechanism for holding a set of connections that
                can be used across multiple threads in an application.  Connection pools help
                improve performance and reduce server load by reusing connections for multiple
                requests and eliminating the expense of establishing and tearing down connections.
              </p>

              <p>
                The traditional means of interacting with a connection pool is to check out a
                connection from the pool, use that connection for the desired operation(s), and
                then return the connection back to the pool so that it can be reused for subsequent
                requests within the application.  This approach is available for use with the
                UnboundID LDAP SDK for Java, and it is the recommended approach if it is necessary
                to process multiple operations over the same physical connection.  However, care
                must be taken to ensure that any connection taken from the pool is returned to the
                pool.
              </p>

              <p>
                In addition, because the <tt>com.unboundid.ldap.sdk.LDAPConnectionPool</tt> class
                implements the <tt>com.unboundid.ldap.sdk.LDAPinterface</tt> interface, a
                connection pool can be used in much the same way as a single
                <tt>LDAPConnection</tt> object.  This is convenient for cases in which the
                application only needs to perform a single request, or if it will perform multiple
                operations but they do not necessarily need to be over the same physical
                connection.  It shares many of the same methods as the <tt>LDAPConnection</tt>
                class, and therefore add, compare, delete, modify, modify DN, and search operations
                can be performed in a connection pool in the same way as with a single connection.
                These methods will encapsulate the process of checking out a connection, performing
                the operation, and returning the connection back to the pool.
              </p>

              <p></p>
              <h3>Creating a Connection Pool</h3>

              <p>
                The <tt>LDAPConnectionPool</tt> class has the following constructors:
              </p>

              <ul>
                <li>
                  <tt>LDAPConnectionPool(LDAPConnection connection, int numConnections)</tt>
                </li>

                <li>
                  <tt>LDAPConnectionPool(LDAPConnection connection, int initialConnections,
                                         int maxConnections)</tt>
                </li>

                <li>
                  <tt>LDAPConnectionPool(LDAPConnection connection, int initialConnections,
                                         int maxConnections, PostConnectProcessor postConnectProcessor)</tt>
                </li>

                <li>
                  <tt>LDAPConnectionPool(ServerSet serverSet, BindRequest bindRequest, int numConnections)</tt>
                </li>

                <li>
                  <tt>LDAPConnectionPool(ServerSet serverSet, BindRequest bindRequest,
                                         int initialConnections, int maxConnections)</tt>
                </li>

                <li>
                  <tt>LDAPConnectionPool(ServerSet serverSet, BindRequest bindRequest,
                                         int initialConnections, int maxConnections,
                                         PostConnectProcessor postConnectProcessor)</tt>
                </li>
              </ul>

              <p>
                The first three constructors provide the ability to create a connection pool with
                a specified number of connections created based on the provided connection.  The
                given connection will be part of the pool, and then other connections will be
                created with the same options, address, port, and bind state as that connection.
              </p>

              <p>
                The last three constructors provide a means of creating a connection pool based on
                a server set.  This provides the ability to have a connection pool with
                connections established across multiple servers so that operations performed in
                the pool may be load balanced across those servers.  See the
                <a href="failover-load-balancing.${EXTENSION}">Client-Side Failover and Load Balancing</a>
                document for more information on creating and using server set objects.
              </p>

              <p>
                The LDAP SDK also provides an <tt>LDAPThreadLocalConnectionPool</tt> class which
                is similar to the <tt>LDAPConnectionPool</tt> class but maintains a separate
                connection per client thread rather than a common pool of connections that may be
                shared by multiple threads.  This connection pool implementation may be easier to
                configure in many cases because it does not require explicitly specifying the
                number of connections to maintain.  These connection pools may be created using
                any of the following constructors:
              </p>

              <ul>
                <li>
                  <tt>LDAPThreadLocalConnectionPool(LDAPConnection connection)</tt>
                </li>

                <li>
                  <tt>LDAPThreadLocalConnectionPool(LDAPConnection connection,
                                                    PostConnectProcessor postConnectProcessor)</tt>
                </li>

                <li>
                  <tt>LDAPThreadLocalConnectionPool(ServerSet serverSet, BindRequest bindRequest)</tt>
                </li>

                <li>
                  <tt>LDAPThreadLocalConnectionPool(ServerSet serverSet, BindRequest bindRequest,
                                                    PostConnectProcessor postConnectProcessor)</tt>
                </li>
              </ul>

              <p></p>
              <h3>Checking Out and Returning Connections</h3>

              <p>
                In order to check out a connection from the pool, use the <tt>getConnection()</tt>
                method.  If the pool has one or more connections available, one of those
                connections will be taken and returned to the caller.  If there are no connections
                available, then the pool will wait for a new connection to become available and/or
                will create a new connection and return it.  The behavior in this condition may be
                controlled using the <tt>setMaxWaitTime</tt> and <tt>setCreateIfNecessary</tt>
                methods.  If the maximum wait time is set to a positive value, then the pool will
                wait up to that number of milliseconds for a connection to become available, or it
                will not wait at all if it is set to a value of zero.  If there is still no
                connection available, then the SDK will either create a new connection (if
                <tt>createIfNecessary()</tt> returns <tt>true</tt>) and return it to the client or
                throw an exception.
              </p>

              <p>
                Whenever a connection is no longer needed, it can be returned to the pool using the
                <tt>releaseConnection()</tt> method.  If the caller knows that there is a problem
                with the connection and it may no longer be valid, then the
                <tt>releaseDefunctConnection()</tt> method should be called instead and that
                connection will be closed and a new connection will be created to take its place.
              </p>

              <p>
                Note that calling the <tt>close</tt> method on an <tt>LDAPConnection</tt> object
                that is associated with a connection pool will cause that connection to be returned
                to the pool rather than actually closing the connection.  However, in order to
                avoid accidentally closing a connection if it may not be associated with a pool,
                then it is recommended that the <tt>releaseConnection</tt> method be used instead
                to return a connection if it is known to be part of a pool.
              </p>

              <p></p>
              <h3>Performing Operations on Pooled Connections</h3>

              <p>
                As noted above, the <tt>LDAPConnectionPool</tt> class implements the
                <tt>LDAPInterface</tt> interface, so all of the following methods operate the same
                as they do for a single <tt>LDAPConnection</tt> object, using a connection that is
                temporarily checked out of the pool and returned after the operation processing is
                complete:
              </p>

              <ul>
                <li><tt>add</tt></li>
                <li><tt>compare</tt></li>
                <li><tt>delete</tt></li>
                <li><tt>getEntry</tt></li>
                <li><tt>getRootDSE</tt></li>
                <li><tt>getSchema</tt></li>
                <li><tt>modify</tt></li>
                <li><tt>modifyDN</tt></li>
                <li><tt>search</tt></li>
              </ul>

              <p>
                Note that it is also possible to process bind and extended operations in the same
                manner, but care must be taken when processing these operations because they can
                impact the state of the associated connection in a manner that may adversely impact
                future operations on the same connection.  In particular, StartTLS extended
                operations should never be processed over pooled connections, and bind operations
                should only be performed if it is known that subsequent operations will not be
                adversely impacted by changing the authorization identity for the associated
                connection.
              </p>

              <p>
                If it is necessary to process operations with different authorization identities
                using pooled connections, then it is recommended that the proxied authorization
                control be used to identify the authorization identity for the target operation.
                See the <a href="controls.${EXTENSION}">Using Standard Controls</a> document for
                information on using the proxied authorization control.
              </p>

              <p></p>
              <h3>Processing Multiple Requests Using a Single Connection</h3>

              <p>
                The connection pool implementation provides a method that may be used to process
                multiple requests over a single pooled connection.  That method is:
              </p>

              <pre>
public List&lt;LDAPResult&gt; processRequests(final List&lt;LDAPRequest&gt; requests,
                                        final boolean continueOnError)
       throws LDAPException
</pre>

              <p>
                This method will check out a connection from the pool and use it to process each of
                the requests in the order they were provided and will release the connection back
                to the pool before returning a list containing the results for those operations.
                The <tt>continueOnError</tt> flag may be used to control whether it should continue
                processing subsequent requests if a problem occurs while processing any of the
                requests.
              </p>

              <p></p>
              <h3>Closing a Connection Pool</h3>

              <p>
                When a connection pool is no longer needed, you may call the <tt>close()</tt>
                method to cause all connections to be closed.
              </p>

              <p></p>
              <h3>Using Separate Servers for Read and Write Operations</h3>

              <p>
                The <tt>LDAPReadWriteConnectionPool</tt> class provides the ability to define
                different sets of servers for read and write operations.  There are two
                constructors available for use:
              </p>

              <ul>
                <li>
                  <tt>LDAPReadWriteConnectionPool(LDAPConnection readConnection, int initialReadConnections, int maxReadConnections, LDAPConnection writeConnection, int initialWriteConnections, int maxWriteConnections)</tt>
                </li>

                <li>
                  <tt>LDAPReadWriteConnectionPool(LDAPConnectionPool readPool, LDAPConnectionPool writePool)</tt>
                </li>
              </ul>

              <p>
                All write operations (add, delete, modify, and modify DN) will be processed using
                connections from the "write" set, and all read operations (bind, compare, and
                search, as well as the <tt>getEntry</tt>, <tt>getRootDSE</tt>, and
                <tt>getSchema</tt> methods) will use the "read" set.  Methods are available for
                obtaining connections from either pool, and it is also possible to process
                operations in the context of the pool.  This connection pool implementation also
                implements the <tt>LDAPInterface</tt> interface, so it can be used in much the
                same way as the <tt>LDAPConnection</tt> and <tt>LDAPConnectionPool</tt> classes.
              </p>
